﻿using Framework.Components;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;

namespace Framework.Utils
{
    /// <summary>
    /// http访问
    /// </summary>
    public static class HttpUtils
    {

        /// <summary>
        /// Get访问
        /// </summary>
        /// <param name="url"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static byte[] Get(string url, Dictionary<string, object> args)
        {
            HttpWebRequest request = WebRequest.Create(Url(url, args)) as HttpWebRequest;
            SetDefualtProperty(request);
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";
            // 执行
            return Execute(request, null);
        }

        /// <summary>
        /// Post 访问
        /// </summary>
        /// <param name="url"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static byte[] Post(string url, Dictionary<string, object> args)
        {
            byte[] data = null;
            // 封装参数
            string paramStr = UrlEncode(args, Encoding.UTF8);
            if (!string.IsNullOrEmpty(paramStr))
            {
                data = Encoding.UTF8.GetBytes(paramStr.ToString());
            }
            // 执行访问
            return Post(url, data);
        }

        /// <summary>
        /// Post访问
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] Post(string url, byte[] data)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            SetDefualtProperty(request);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            //request.ContentType = "application/x-java-serialized-object";
            // 执行
            return Execute(request, data);
        }

        /// <summary>
        /// 执行访问
        /// </summary>
        /// <param name="request"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private static byte[] Execute(HttpWebRequest request, byte[] data)
        {
            Stream reqStream = null;
            Stream respStream = null;
            try
            {
                // 写入数据
                int dsize = (data != null) ? data.Length : 0;
                if (dsize > 0)
                {
                    using (reqStream = request.GetRequestStream())
                    {
                        reqStream.Write(data, 0, dsize);
                        reqStream.Flush();
                        reqStream.Close();
                    }
                }

                // 获取结果
                var response = request.GetResponse() as HttpWebResponse;
                if(response.StatusCode != HttpStatusCode.OK)
                {
                    return null;
                }

                // 读取返回数据
                using (respStream = response.GetResponseStream())
                {
                    long maxSize = response.ContentLength;
                    maxSize = (maxSize <= 0) ? 1024 * 1024 : maxSize;
                    return ReadBytes(respStream, maxSize, 10 * 1024);
                }
            }
            catch(Exception e)
            {
                Log.Error("http 访问错误!" + request.RequestUri, e);
            }
            finally
            {
                if (reqStream != null)
                {
                    reqStream.Close();
                    reqStream = null;
                }
                if (respStream != null)
                {
                    respStream.Close();
                    respStream = null;
                }
            }
            return null;
        }

        /// <summary>
        /// 读取返回数据
        /// </summary>
        /// <param name="s"></param>
        /// <param name="maxBuffer"></param>
        /// <param name="tempBuffer"></param>
        /// <returns></returns>
        private static byte[] ReadBytes(Stream s, long maxSize, int tempSize)
        {
            //long slen = s.Length;
            byte[] buff = new byte[maxSize];
            try
            {
                int totalSize = 0;
                byte[] temp = new byte[tempSize];
                while (true)
                {
                    int size = s.Read(temp, 0, tempSize);
                    if (size <= 0)
                    {
                        break; // 数据读取完毕
                    }
                    // 检测缓存是否够用
                    if (totalSize + size > maxSize)
                    {
                        throw new Exception("缓存数据不足");
                    }
                    // 写入数据
                    Array.Copy(temp, 0, buff, totalSize, size);
                    totalSize += size;
                }
                // 如果长度刚刚好, 不用复制一份出来.
                if (totalSize == maxSize) { return buff; }
                // 重新提取一份长度出来
                byte[] ret = new byte[totalSize];
                Array.Copy(buff, 0, ret, 0, totalSize);
                return ret;
            }
            catch (Exception e)
            {
                Log.Error("读取http数据错误! ", e);
            }
            return null;
        }


        /// <summary>
        /// url拼接
        /// </summary>
        /// <param name="url"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static string Url(string url, Dictionary<string, object> args)
        {
            string paramStr = UrlEncode(args, Encoding.UTF8);
            return (!string.IsNullOrEmpty(paramStr)) ? url + "?" + paramStr : url;
        }
        
        /// <summary>
        /// url加密
        /// </summary>
        public static string UrlEncode(Dictionary<string, object> args, Encoding encoding)
        {
            int asize = (args != null) ? args.Count : 0;
            if (asize <= 0) { return null; }
            // 生成字符串
            StringBuilder strBdr = new StringBuilder();
            // 遍历数据
            int index = 0;
            foreach (KeyValuePair<string, object> pair in args)
            {
                if (pair.Value == null) { continue; }
                if (index++ > 0)
                {
                    strBdr.Append("&");
                }
                strBdr.Append(pair.Key);
                strBdr.Append("=");
                strBdr.Append(HttpUtility.UrlEncode(pair.Value.ToString(), encoding));
            }
            return strBdr.ToString();
        }
        

        /// <summary>
        /// 设置默认参数
        /// </summary>
        private static void SetDefualtProperty(HttpWebRequest request)
        {
            request.Proxy = null;
            // http连接后不保持连接
            request.KeepAlive = false;
            // 设置连接主机超时（单位：毫秒）
            request.ContinueTimeout = 10 * 1000;
            // 设置从主机读取数据超时（单位：毫秒）
            request.ReadWriteTimeout = 10 * 1000;
            request.Timeout = 10 * 1000;
        }
    }
}
